--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
docs/meshchatx_linux_sandbox.md e8e5128bc67cd3e8540bcd9f4e9be1b8d43db36a (e8e5128b) Text, 6.37 KB
Tc9d1d9# MeshChatX on Linux: Firejail and Bubblewrap
This page shows how to run Ta5d6ff`meshchat` under **Firejail** or **Bubblewrap** (Ta5d6ff`bwrap`) on Linux. Use this when you install MeshChatX natively (wheel, package, or Poetry) and want an extra layer of filesystem and process isolation compared to running the binary directly.
These tools do **not** replace a full virtual machine or hardware-enforced boundary. They reduce exposure of your home directory and other paths the process can write to, when you configure them with tight whitelists or bind mounts.
**Containers:** If you already run MeshChatX with Docker or Podman, that is a different isolation model; this document is aimed at **host-installed** Ta5d6ff`meshchat`.
Tc9d1d9## Prerequisites
Install one or both from your distribution:
Tff7b72- **Firejail:** package name is usually Ta5d6ff`firejail`.
Tff7b72- **Bubblewrap:** package name is usually Ta5d6ff`bubblewrap`; the binary is Ta5d6ff`bwrap`.
You need a working Ta5d6ff`meshchat` on your Ta5d6ff`PATH` (for example after Ta5d6ff`pipx install`, Ta5d6ff`pip install --user`, or a distro package).
Pick a **dedicated data directory** for sandboxed runs so you do not mix permissions or policies with a non-sandboxed install. The examples below use:
Ta5d6ff```Ta5d6ffbash
Te6edf3DATATff7b72=Ta5d6ff"Tffd700${Te6edf3XDG_DATA_HOMETff7b72:-Te6edf3$HOMETb4b4b4/.local/shareTffd700}Ta5d6ff/meshchatx-sandboxTa5d6ff"
mkdir -p Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Ta5d6ff```
Adjust paths if you prefer another location.
Tc9d1d9## Firejail
Firejail applies a profile (or defaults) on top of your command. For MeshChatX you typically want:
Tff7b72- **Network** left available so Reticulum and the web UI can work (do not use Ta5d6ff`--net=none` unless you know you need it).
Tff7b72- **Writable** only your chosen data directory (and anything else the app truly needs).
Tc9d1d9### Installed `meshchat` (pip, pipx, or system package)
Ta5d6ff```Ta5d6ffbash
Te6edf3DATATff7b72=Ta5d6ff"Tffd700${Te6edf3XDG_DATA_HOMETff7b72:-Te6edf3$HOMETb4b4b4/.local/shareTffd700}Ta5d6ff/meshchatx-sandboxTa5d6ff"
mkdir -p Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
firejail --quiet Tffea00\
--whitelistTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff" Tffea00\
meshchat --headless --host T79c0ff127.0.0.1 Tffea00\
--storage-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Tffea00\
--reticulum-config-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Ta5d6ff```
If the default profile blocks something MeshChatX needs, you can start from a looser base and tighten later, for example:
Ta5d6ff```Ta5d6ffbash
firejail --noprofile --whitelistTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff" Tffea00\
meshchat --headless --host T79c0ff127.0.0.1 Tffea00\
--storage-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Tffea00\
--reticulum-config-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Ta5d6ff```
Ta5d6ff`--noprofile` disables many Firejail restrictions; treat it as a stepping stone, not the final hardening.
Tc9d1d9### From source with Poetry
Poetry needs the project tree and the virtualenv. Example:
Ta5d6ff```Ta5d6ffbash
Tffa657cd /path/to/reticulum-meshchatX
Te6edf3DATATff7b72=Ta5d6ff"Tffd700${Te6edf3XDG_DATA_HOMETff7b72:-Te6edf3$HOMETb4b4b4/.local/shareTffd700}Ta5d6ff/meshchatx-sandboxTa5d6ff"
Te6edf3VENVTff7b72=Ta5d6ff"Tff7b72$(poetry env info -pTff7b72)Ta5d6ff"
mkdir -p Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
firejail --quiet Tffea00\
--whitelistTff7b72=Ta5d6ff"Tff7b72$(Tffa657pwdTff7b72)Ta5d6ff" Tffea00\
--whitelistTff7b72=Ta5d6ff"Te6edf3$VENVTa5d6ff" Tffea00\
--whitelistTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff" Tffea00\
poetry run meshchat --headless --host T79c0ff127.0.0.1 Tffea00\
--storage-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Tffea00\
--reticulum-config-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Ta5d6ff```
You may need extra Ta5d6ff`--whitelist=` entries if Poetry or dependencies read config elsewhere (for example under Ta5d6ff`$HOME/.config`).
Tc9d1d9### USB serial (RNode or similar)
If Reticulum talks to a radio over a serial device, Firejail may need explicit access to TTY devices, for example:
Ta5d6ff```Ta5d6ffbash
firejail --noblacklistTff7b72=/dev/ttyACM0 --noblacklistTff7b72=/dev/ttyUSB0 Tffea00\
...
Ta5d6ff```
Use the device nodes your system actually exposes (Ta5d6ff`dmesg`, Ta5d6ff`ls /dev/tty*`).
Tc9d1d9## Bubblewrap (`bwrap`)
Bubblewrap does not ship profiles; you list every mount and option. The pattern below keeps the **whole root filesystem read-only**, mounts a **writable tmpfs** on Ta5d6ff`/tmp`, and makes **only** your data directory writable at its normal path. **Network namespaces are not changed**, so Reticulum and TCP/UDP behave like an unsandboxed process unless you add Ta5d6ff`--unshare-net` (which usually breaks mesh networking).
Tc9d1d9### Installed `meshchat`
Ta5d6ff```Ta5d6ffbash
Te6edf3DATATff7b72=Ta5d6ff"Tffd700${Te6edf3XDG_DATA_HOMETff7b72:-Te6edf3$HOMETb4b4b4/.local/shareTffd700}Ta5d6ff/meshchatx-sandboxTa5d6ff"
mkdir -p Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Tffa657exec bwrap Tffea00\
--die-with-parent Tffea00\
--new-session Tffea00\
--proc /proc Tffea00\
--dev /dev Tffea00\
--ro-bind / / Tffea00\
--tmpfs /tmp Tffea00\
--bind Ta5d6ff"Te6edf3$DATATa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff" Tffea00\
--uid Ta5d6ff"Tff7b72$(id -uTff7b72)Ta5d6ff" --gid Ta5d6ff"Tff7b72$(id -gTff7b72)Ta5d6ff" Tffea00\
meshchat --headless --host T79c0ff127.0.0.1 Tffea00\
--storage-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Tffea00\
--reticulum-config-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Ta5d6ff```
Notes:
Tff7b72- If Ta5d6ff`meshchat` lives only inside a venv that is **not** under Ta5d6ff`$DATA`, the read-only root still allows **reading** that path; you do not have to bind-mount the venv separately unless you also need writes there.
Tff7b72- Distributions that merge Ta5d6ff`/` and Ta5d6ff`/usr` (merged-usr) still work with Ta5d6ff`--ro-bind / /` on typical glibc setups. If Ta5d6ff`bwrap` fails with missing library paths, add the extra Ta5d6ff`--ro-bind` lines your distro documents (for example Ta5d6ff`/lib64`).
Tc9d1d9### From source with Poetry
Bind the repository and the Poetry venv read-only, and keep Ta5d6ff`DATA` writable:
Ta5d6ff```Ta5d6ffbash
Tffa657cd /path/to/reticulum-meshchatX
Te6edf3DATATff7b72=Ta5d6ff"Tffd700${Te6edf3XDG_DATA_HOMETff7b72:-Te6edf3$HOMETb4b4b4/.local/shareTffd700}Ta5d6ff/meshchatx-sandboxTa5d6ff"
Te6edf3VENVTff7b72=Ta5d6ff"Tff7b72$(poetry env info -pTff7b72)Ta5d6ff"
mkdir -p Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Te6edf3PROJTff7b72=Ta5d6ff"Tff7b72$(Tffa657pwdTff7b72)Ta5d6ff"
Tffa657exec bwrap Tffea00\
--die-with-parent Tffea00\
--new-session Tffea00\
--proc /proc Tffea00\
--dev /dev Tffea00\
--ro-bind / / Tffea00\
--tmpfs /tmp Tffea00\
--bind Ta5d6ff"Te6edf3$DATATa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff" Tffea00\
--ro-bind Ta5d6ff"Te6edf3$PROJTa5d6ff" Ta5d6ff"Te6edf3$PROJTa5d6ff" Tffea00\
--ro-bind Ta5d6ff"Te6edf3$VENVTa5d6ff" Ta5d6ff"Te6edf3$VENVTa5d6ff" Tffea00\
--uid Ta5d6ff"Tff7b72$(id -uTff7b72)Ta5d6ff" --gid Ta5d6ff"Tff7b72$(id -gTff7b72)Ta5d6ff" Tffea00\
--setenv PATH Ta5d6ff"Te6edf3$VENVTa5d6ff/bin:Te6edf3$PATHTa5d6ff" Tffea00\
--chdir Ta5d6ff"Te6edf3$PROJTa5d6ff" Tffea00\
poetry run meshchat --headless --host T79c0ff127.0.0.1 Tffea00\
--storage-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Tffea00\
--reticulum-config-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Ta5d6ff```
Ta5d6ff`poetry` itself must be reachable on Ta5d6ff`PATH` inside the sandbox (often under Ta5d6ff`/usr` or Ta5d6ff`$HOME/.local/bin`, both visible with Ta5d6ff`--ro-bind / /`). If Ta5d6ff`poetry run` fails because it cannot read Ta5d6ff`~/.config/poetry`, add a read-only bind for that directory or invoke the venv interpreter directly instead of Ta5d6ff`poetry run`:
Ta5d6ff```Ta5d6ffbash
Tffa657exec bwrap Tffea00\
... same mounts as above ... Tffea00\
--setenv PATH Ta5d6ff"Te6edf3$VENVTa5d6ff/bin:Te6edf3$PATHTa5d6ff" Tffea00\
--chdir Ta5d6ff"Te6edf3$PROJTa5d6ff" Tffea00\
meshchat --headless --host T79c0ff127.0.0.1 Tffea00\
--storage-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Tffea00\
--reticulum-config-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Ta5d6ff```
(Use the Ta5d6ff`meshchat` script or Ta5d6ff`python -m` entry point from Ta5d6ff`$VENV/bin` if your install exposes it there.)
Tc9d1d9### USB serial under Bubblewrap
You may need a clearer view of devices than the minimal Ta5d6ff`--dev /dev` provides. Options include Ta5d6ff`--dev-bind /dev /dev` (broader device exposure) or binding only the specific character device. Balance convenience against attack surface.
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────